package org.dxw.common.excel;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dxw.common.enums.GlobalResultEnum;
import org.dxw.common.RunAndCatchExcep;
import org.dxw.resp.BaseResponse;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Function;

/**
 * @Author
 * @Date
 * @Description
 */
@Slf4j
public class ExportUtil {


    /**
     *
     * @param response
     * @throws Exception
     */
    public static void handlerExportExcel(HttpServletResponse response, String exportFileName, RunAndCatchExcep runnable){
        try{
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String encode = URLEncoder.encode(exportFileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encode + ".xlsx");
            runnable.run();
        }catch (Exception e){
            log.error("导出文件{}发生异常!", exportFileName, e);
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            try{
                response.getWriter().println(JSON.toJSONString(BaseResponse.error(GlobalResultEnum.ERROR)));
            }catch (IOException ex){
                log.error("发生异常", ex);
            }
        }

    }

    /**
     * @param rowOffset 第一行数据的行号
     * @param datas
     * @param mergeParams
     * @return 生成的CellRangeAddress放入到下面的map里
     * @see MyCellWriteHandler#setSheetCellRange(Map)
     *
     */
    public static List<CellRangeAddress> generatorCellRange(int rowOffset, List datas, List<MergeParam> mergeParams){
        if(CollUtil.isEmpty(datas) || CollUtil.isEmpty(mergeParams)){
            return Collections.emptyList();
        }

        List<CellRangeAddress> cellRangeAddresses = new LinkedList<>();
        for (MergeParam mergeParam : mergeParams) {
            List<Integer> mergeRowIndexStart = new ArrayList<>(datas.size() + 1);
            List<Integer> mergeRowIndexEnd = new ArrayList<>(datas.size() + 1);
            //初始化容器
            for (int i = 0; i < datas.size()+1; i++) {
                mergeRowIndexStart.add(null);
                mergeRowIndexEnd.add(null);
            }
            mergeParam.setMergeRowIndexStart(mergeRowIndexStart);
            mergeParam.setMergeRowIndexEnd(mergeRowIndexEnd);
        }


        for (int i = 0; i < datas.size(); i++) {
            Object data = datas.get(i);
            for (MergeParam mergeParam : mergeParams) {
                Function keyExtractor = mergeParam.getKeyExtractor();
                Object apply = keyExtractor.apply(data);
                if(ObjectUtil.equal(mergeParam.getLastKeyVal(), apply)){
                    mergeParam.getMergeRowIndexEnd().set(mergeParam.getMergeNum(), rowOffset+i);
                }else{
                    mergeParam.setMergeNum(mergeParam.getMergeNum()+1);
                    mergeParam.getMergeRowIndexStart().set(mergeParam.getMergeNum(), rowOffset+i);
                }
                mergeParam.setLastKeyVal(apply);
            }
        }

        for (MergeParam mergeParam : mergeParams) {
            List<Integer> mergeRowIndexStart = mergeParam.getMergeRowIndexStart();
            List<Integer> mergeRowIndexEnd = mergeParam.getMergeRowIndexEnd();
            for (int i = 0; i < mergeRowIndexStart.size(); i++) {
                if(mergeRowIndexStart.get(i) == null || mergeRowIndexEnd.get(i) == null
                        || mergeRowIndexStart.get(i) >= mergeRowIndexEnd.get(i)){
                    continue;
                }
                List<Integer> mergeColumnIndex = mergeParam.getMergeColumnIndex();
                for (Integer columnIndex : mergeColumnIndex) {
                    CellRangeAddress cellAddresses = new CellRangeAddress(mergeRowIndexStart.get(i), mergeRowIndexEnd.get(i), columnIndex, columnIndex);
                    cellRangeAddresses.add(cellAddresses);
                }
            }
        }
        return cellRangeAddresses;
    }



    /**
     * @warn 导出文件名在 handlerExport中设置了
     * @see ExportUtil#handlerExportExcel
     * @param data
     * @param <T>
     */
    public <T> void simpleWrite(HttpServletResponse response, List<T> data, Class<T> clz, String sheetName) throws IOException {
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        WriteSheet sheet = EasyExcel.writerSheet(0, sheetName).head(clz).build();
        excelWriter.write(data, sheet);
        excelWriter.finish();
    }


}
